package com.ironman.sailboat.mobile.runner;

import cn.hutool.core.util.StrUtil;
import com.ironman.sailboat.mobile.computer.v2.TrainComputer;
import com.ironman.sailboat.mobile.context.MockConfigContext;
import com.ironman.sailboat.mobile.dataobject.td.Gps;
import com.ironman.sailboat.mobile.threadpool.ThreadPool;
import com.mybatisflex.core.row.Db;
import com.mybatisflex.core.row.Row;
import com.mybatisflex.core.row.RowUtil;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.noear.snack.ONode;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * description 传感器runner
 * company 铁人科技
 *
 * @author 陈浩杰
 * @date 2023/12/15 9:48
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class GpsMockRunner extends AbstractMockRunner implements ApplicationListener<ApplicationReadyEvent> {

    final TrainComputer trainComputer;

    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        log.info("GpsOriginalRunner init start");
        ThreadPool.FIXED_EXECUTOR.submit(new Runnable() {
            @SneakyThrows
            @Override
            public void run() {
                String sql = "SELECT ts, longitude, latitude, gps_speed, gps_direction, declination, valid, gps_fill_type FROM `sailboat`.`training_data` WHERE tenant_code = ? AND level_id = ? AND m_hm_id = ? AND ts >=? AND ts <= ?";
                List<Row> rows = Db.selectListBySql(sql, MockConfigContext.fromTenantCode(), MockConfigContext.fromLevelId(), MockConfigContext.fromMHmId(), getSysTrainingProperties().getStartTime(), getSysTrainingProperties().getEndTime());
                log.info("Gps rows: {}", rows.size());
                setStartAndEndTime(rows);
                Map<Date, Gps> dateMap = rows.stream().collect(Collectors.toMap(n -> n.getDate("ts"), n -> RowUtil.toEntity(n, Gps.class)));
                COUNT_DOWN_LATCH.countDown();
                COUNT_DOWN_LATCH.await();
                traceBackData(date -> {
                    Gps gps = dateMap.get(date);
                    if (Objects.isNull(gps)) {
                        return null;
                    }
                    if (StrUtil.isBlank(gps.getGpsFillType())) {
                        return null;
                    }
                    boolean fillType = "1".equals(gps.getGpsFillType());
                    if (fillType) {
                        return null;
                    }
                    if (gps.getValid()) {
                        trainComputer.gps(Double.valueOf(gps.getLongitude()), Double.valueOf(gps.getLatitude()), gps.getGpsDirection(), BigDecimal.valueOf(gps.getGpsSpeed()).setScale(4, RoundingMode.HALF_UP).doubleValue());
                    }
                    String dataFormat = "{},{},{},{},{},{}";
                    return ONode.newObject().set("dataType", "gps").set("data", StrUtil.format(dataFormat,
                            gps.getValid() ? "A" : "V",
                            gps.getValid() ? gps.getLongitude() : "",
                            gps.getValid() ? gps.getLatitude() : "",
                            gps.getValid() ? BigDecimal.valueOf(gps.getGpsSpeed()).setScale(4, RoundingMode.HALF_UP).doubleValue() : "",
                            gps.getValid() ? gps.getGpsDirection() : "",
                            gps.getValid() ? gps.getDeclination() : ""
                    ));
                });
            }
        });
        log.info("GpsOriginalRunner init finish");
    }
}
